from fastapi import APIRouter, HTTPException

import numpy as np
import pandas as pd
import os

import statsmodels.api as sm
from app.common.utils import get_current_datetime_str, DEST_DIR
from pydantic import BaseModel

router = APIRouter(prefix="/generating", tags=["data_generating"])


@router.get("/varient_view", description="全局变量测试接口")
async def varient_test():
    return {"DEST_DIR": DEST_DIR}

class ParaItem(BaseModel):
    low_x1: int = 0
    high_x1: int = 200
    low_x2: int = 2
    high_x2: int = 200
    n_samples: int = 150
    beta0: float = 6
    beta1: float = 2
    beta2: float = 5
    save_file_name:str = 'normal_regression_data'


@router.post(
    "/regression", description="生成回归分析数据、描述性统计,  y = param_data.beta0 + param_data.beta1 * x1 + param_data.beta2 * x2 + epsilon"
)
async def regression_analysis_data(param_data: ParaItem):

    # 设置随机种子以确保结果可重复
    np.random.seed(0)

    # 定义样本数量
    n_samples = param_data.n_samples

    # 定义自变量x1和x2
    # x1 = np.random.rand(n_samples)  # 生成0到1之间的随机数
    x1 = np.random.randint(param_data.low_x1, param_data.high_x1, size=n_samples)

    x2 = np.random.randint(param_data.low_x2, param_data.high_x2, n_samples)  # 同样生成0到1之间的随机数


    # 传入3个系数，定义误差项epsilon，这里假设误差项来自标准正态分布
    epsilon = np.random.randn(n_samples)

    # 根据回归方程生成y
    y = param_data.beta0 + param_data.beta1 * x1 + param_data.beta2 * x2 + epsilon

    # 将数据转换为pandas DataFrame
    regression_data = pd.DataFrame({"x1": x1, "x2": x2, "y": y})

    # return {"data": regression_data.to_json(orient="records")}
    # 数据描述性统计
    rg_describe = regression_data.describe()
    # print(rg_describe)
    # print(regression_data.describe().to_json(orient="records"))

    # return {"data": rg_describe.to_dict(orient="index")}

    file_full_path = os.path.join(DEST_DIR, param_data.save_file_name + '_' + get_current_datetime_str() + ".csv")
    regression_data.to_csv(f"{file_full_path}", index=False)
    # 返回包含列名和索引的JSON对象
    # return {"data": rg_describe.to_json(orient="index")}
    return {"dataPath": file_full_path, "regression_describe_data": rg_describe}

class VariableItem(BaseModel):
    name: str
    low: int
    high: int
    beta: float

class DynamicParaItem(BaseModel):
    n_samples: int = 150
    beta0: float = 6
    variables: list[VariableItem] = [
        VariableItem(name="x1", low=0, high=200, beta=2.0),
        VariableItem(name="x2", low=2, high=200, beta=5.0)
    ]
    save_file_name: str = 'dynamic_regression_data'

@router.post(
    "/dynamic_regression", 
    description="生成具有动态数量自变量的回归分析数据，支持1-5个自变量"
)
async def dynamic_regression_analysis_data(param_data: DynamicParaItem):
    # 验证自变量数量
    if not 1 <= len(param_data.variables) <= 5:
        raise HTTPException(
            status_code=400,
            detail="自变量数量必须在1到5个之间"
        )
    
    # 检查变量名是否重复
    variable_names = [var.name for var in param_data.variables]
    if len(variable_names) != len(set(variable_names)):
        duplicate_names = [name for name in set(variable_names) if variable_names.count(name) > 1]
        raise HTTPException(
            status_code=400,
            detail=f"变量名重复: {', '.join(duplicate_names)}"
        )
    
    try:
        # 设置随机种子以确保结果可重复
        np.random.seed(0)
        
        # 生成数据字典
        data_dict = {}
        
        # 为每个自变量生成数据
        for var in param_data.variables:
            x = np.random.randint(var.low, var.high, size=param_data.n_samples)
            data_dict[var.name] = x
        
        # 生成误差项
        epsilon = np.random.randn(param_data.n_samples)
        
        # 计算因变量y
        y = param_data.beta0 + epsilon
        for var in param_data.variables:
            y += var.beta * data_dict[var.name]
        
        # 将y添加到数据字典
        data_dict["y"] = y
        
        # 转换为DataFrame
        regression_data = pd.DataFrame(data_dict)
        
        # 计算描述性统计
        rg_describe = regression_data.describe()
        
        # 保存数据
        file_full_path = os.path.join(DEST_DIR, param_data.save_file_name + '_' + get_current_datetime_str() + ".csv")
        regression_data.to_csv(f"{file_full_path}", index=False)
        
        return {
            "dataPath": file_full_path, 
            "regression_describe_data": rg_describe
        }
    except Exception as e:
        raise HTTPException(
            status_code=500,
            detail=f"生成数据时发生错误: {str(e)}"
        )
